home *** CD-ROM | disk | FTP | other *** search
/ A.C.E. 2 / ACE CD 2.iso / FILES / UTILS / GAMESDS3.DMS / GAMESDS3.adf / GDS_Examples.lha / Examples / MoonRocks / game.c < prev    next >
C/C++ Source or Header  |  1994-11-14  |  35KB  |  1,260 lines

  1. /*
  2.  * MOON ROCKS by Alan Bland.  This is an example game using the
  3.  * GameSmith Development System.  You are free to use portions of
  4.  * this source code for any purpose whatsoever.  This isn't
  5.  * necessarily the best way to use GDS for this type of game,
  6.  * but it shows usage of many of the components of GDS (anims,
  7.  * anim complexes, sounds, scrolling background, multiple viewports,
  8.  * RastPort usage, background collision detection).
  9.  *
  10.  * This game won't work on an OCS Amiga because of the large
  11.  * scrolling superbitmap.  It may also require 1 meg of chip ram.
  12.  *
  13.  * The elvis animation is based on the "tiny elvis" public domain
  14.  * screen hack for Microsoft Windows.  I changed it around quite
  15.  * a bit to reduce the color palette and to make different dancing
  16.  * motions from the original.
  17.  *
  18.  * Call CYBERMIGA BBS at 1-303-939-9923.  Lots of Amiga files!
  19.  */
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <fcntl.h>
  25. #include <math.h>
  26. #include <intuition/intuition.h>
  27. #include <exec/memory.h>
  28. #include <exec/types.h>
  29. #include <graphics/gfx.h>
  30. #include <graphics/gfxbase.h>
  31.  
  32. #include <clib/exec_protos.h>
  33. #include <clib/graphics_protos.h>
  34. #include <clib/intuition_protos.h>
  35.  
  36. #include "GameSmith:GameSmith.h"
  37. #include "GameSmith:include/libraries/libptrs.h"
  38. #include "GameSmith:include/proto/all_regargs.h"
  39.  
  40. /* header file for anim complexes */
  41. #include "lc.h"
  42. #include "rs.h"
  43.  
  44. #define DDEPTH  3
  45. #define NUM_COLORS 8
  46.  
  47. #define VP2_HEIGHT 19
  48. #define VP2_DEPTH 3
  49. #define VP2_NUM_COLORS 8
  50.  
  51. #define DWIDTH 320
  52. #define DHEIGHT (200-VP2_HEIGHT-3)
  53. #define DISP_MODE 0
  54.  
  55. #define X_SCROLLPOS (DWIDTH/3)
  56. #define Y_SCROLLTOP (DHEIGHT/4)
  57. #define Y_SCROLLBOT (DHEIGHT/2)
  58.  
  59. /* this defines the vertical position below which the spacecraft
  60.  * can collide with background objects.  see main loop comments.
  61.  */
  62. #define GROUND_THRESHOLD (bmheight-52)
  63.  
  64. /* this is how close (pixels) we must land to the target to win the game */
  65. #define CLOSE_ENOUGH 250
  66.  
  67. #define MAX_FUEL 3000
  68. #define LOW_FUEL 300
  69.  
  70. /* physical constants */
  71. #define MAX_ALTITUDE 70000.0
  72. #define MAX_RANGE 50000.0
  73. #define GRAVITY 5.0
  74. #define THRUST 10.0
  75. #define SAFE_SPEED 200.0
  76.  
  77. /* To be strictly accurate, I think this should be 60 for NTSC, 50 for PAL */
  78. #define TICKS_PER_SEC 60
  79.  
  80. /* joystick responsiveness - set to 0 for fastest */
  81. #define JOY_INTERVAL 3
  82.  
  83. /* how often to animate the rock star */
  84. #define DANCE_DELAY 5
  85. unsigned char time_to_dance;
  86. short dance_time;
  87. unsigned char rockstar_visible;   /* is he visible? */
  88. unsigned long rockstar_time;      /* next time that he changes animation */
  89. unsigned char allow_rockstar;     /* allow him to materialize */
  90. /*
  91.  * The VP2 bitmap has several different control panel images which we
  92.  * scroll into view as necessary.  The top image is the normal panel.
  93.  * These constants define the scroll offset for each image.
  94.  */
  95. #define VP_PAUSED  VP2_HEIGHT
  96. #define VP_NOWHERE (VP2_HEIGHT*2)
  97. #define VP_VISIBLE (VP2_HEIGHT*3)
  98. #define VP_CRASHED (VP2_HEIGHT*4)
  99. #define VP_SUCCESS (VP2_HEIGHT*5)
  100.  
  101.  
  102. unsigned long lunar_cmap[NUM_COLORS];
  103. unsigned long vp2_cmap[VP2_NUM_COLORS];
  104.  
  105. /*
  106.  * vp is the viewport for the main viewing area.
  107.  * vp2 is the control panel at the bottom of the screen.
  108.  */
  109.  
  110. struct gs_viewport vp2 = {
  111.     NULL,            /* ptr to next viewport */
  112.     vp2_cmap,            /* ptr to color table */
  113.     VP2_NUM_COLORS,         /* number of colors in table */
  114.     NULL,            /* ptr to user copper list */
  115.     VP2_HEIGHT,DWIDTH,VP2_DEPTH,   /* height, width, depth */
  116.     0,0,            /* bmheight, bmwidth */
  117.     DHEIGHT+2,0,         /* top & left viewport offsets */
  118.     0,0,            /* X & Y bitmap offsets */
  119.     0,               /* flags */
  120.     NULL,NULL,            /* 2.xx & above compatibility stuff */
  121.     NULL,NULL,            /* bitmap pointers */
  122.     NULL,            /* future expansion */
  123.     0,0,0,0            /* display clip (use nominal) */
  124. };
  125.  
  126. struct gs_viewport vp = {
  127.     &vp2,            /* ptr to next viewport */
  128.     lunar_cmap,            /* ptr to color table */
  129.     NUM_COLORS,            /* number of colors in table */
  130.     NULL,            /* ptr to user copper list */
  131.     DHEIGHT,DWIDTH,DDEPTH,      /* height, width, depth */
  132.     0,0,            /* bmheight, bmwidth */
  133.     0,0,            /* top & left viewport offsets */
  134.     0,0,            /* X & Y bitmap offsets */
  135.     0,               /* flags */
  136.     NULL,NULL,            /* 2.xx & above compatibility stuff */
  137.     NULL,NULL,            /* bitmap pointers */
  138.     NULL,            /* future expansion */
  139.     0,0,0,0            /* display clip (use nominal) */
  140. };
  141.  
  142. struct display_struct lunar_display = {
  143.     NULL,            /* ptr to previous display view */
  144.     NULL,NULL,            /* 2.xx & above compatibility stuff */
  145.     0,0,            /* X and Y display offsets (1.3 style) */
  146.     DISP_MODE,            /* display mode ID */
  147.     4,4,          /* sprite priorities */
  148.     GSV_DOUBLE|GSV_SCROLLABLE,      /* flags (double buffered, scrollable) */
  149.     &vp,            /* ptr to 1st viewport */
  150.     NULL            /* future expansion */
  151. };
  152.  
  153. struct anim_cplx *lem;         /* the spacecraft anim complex */
  154. struct anim_cplx *rockstar;             /* the rock star anim complex */
  155. struct display_struct *display;      /* points at lunar_display if it got created ok */
  156. struct Interrupt *scroller=NULL;   /* interrupt handler for smooth scrolling */
  157. int dlist=-1;            /* display list used with anim system */
  158. int bmwidth;
  159. int bmheight;
  160. struct RastPort rp;         /* RastPort for writing text to the control panel */
  161. struct BitMap *cp_bitmaps[2];      /* need to double-buffer bitmaps for RastPort */
  162. struct TextAttr sysfont = {      /* control panel will be topaz.8 */
  163.    "topaz.font", 8, 0, 0
  164. };
  165. struct TextFont *myfont;
  166.  
  167. short elapsed_mins;
  168. short elapsed_secs;
  169. short elapsed_ticks;
  170.  
  171. /*
  172.  * The MED module uses channels 0 and 1.  Sound effects are on 2 and 3
  173.  * except for the PING sound, which is only played without music so it's
  174.  * on one of the music channels.
  175.  */
  176. #include "libproto.h"
  177. struct MMD0 *tune;
  178. struct Library *MEDPlayerBase;
  179.    
  180. /*
  181.  * structures and channel assignments for each sound.
  182.  */
  183. #define THRUST_CHANNEL CHANNEL2
  184. #define WHOOP_CHANNEL  CHANNEL3
  185. #define PING_CHANNEL   CHANNEL1
  186. #define FILL_CHANNEL   CHANNEL3
  187. #define KABOOM_CHANNEL CHANNEL2
  188. #define LANDED_CHANNEL CHANNEL3
  189.  
  190. struct sound_struct thrust;
  191. struct sound_struct whoop;
  192. struct sound_struct kaboom;
  193. struct sound_struct landed;
  194. struct sound_struct ping;
  195. struct sound_struct fill;
  196.  
  197. /* the "lc" anim complex contains zillions of short anims showing the
  198.    spacecraft at various rotation angles (increments of 15 degrees),
  199.    with and without flames. the "lc_flame" array lists the anims with
  200.    flames in clockwise rotation order.  "lc_noflame" lists the anims
  201.    without flames. */
  202.  
  203. #define LC_ANIM_COUNT 24
  204.  
  205. short lc_flame[LC_ANIM_COUNT] = {
  206. FLAME00, FLAME15, FLAME30, FLAME45, FLAME60, FLAME75,
  207. FLAME90, FLAME105, FLAME120, FLAME135, FLAME150, FLAME165,
  208. FLAME180, FLAME195, FLAME210, FLAME225, FLAME240, FLAME255,
  209. FLAME270, FLAME285, FLAME300, FLAME315, FLAME330, FLAME345
  210. };
  211. short lc_noflame[LC_ANIM_COUNT] = {
  212. LEM00, LEM15, LEM30, LEM45, LEM60, LEM75,
  213. LEM90, LEM105, LEM120, LEM135, LEM150, LEM165,
  214. LEM180, LEM195, LEM210, LEM225, LEM240, LEM255,
  215. LEM270, LEM285, LEM300, LEM315, LEM330, LEM345
  216. };
  217.  
  218. /* sines and cosines are pre-computed for each 15 degree rotational
  219.    position.  this makes the game fast enough to run on an old
  220.    68000 Amiga without a math chip. */
  221.  
  222. double sinval[LC_ANIM_COUNT] = {
  223. -1.000000, -0.966168, -0.866519, -0.707840, -0.500941, -0.259916,
  224. 0.000000, 0.258771, 0.499914, 0.707002, 0.865927, 0.965862,
  225. 1.000000, 0.966015, 0.866223, 0.707421, 0.500428, 0.259344,
  226. 0.000593, -0.258199, -0.499401, -0.706583, -0.865630, -0.965708
  227. };
  228.  
  229. double cosval[LC_ANIM_COUNT] = {
  230. -0.000889, 0.257913, 0.499144, 0.706373, 0.865482, 0.965631,
  231. 1.000000, 0.965939, 0.866075, 0.707212, 0.500171, 0.259058,
  232. 0.000296, -0.258485, -0.499658, -0.706792, -0.865778, -0.965785,
  233. -1.000000, -0.966092, -0.866371, -0.707630, -0.500684, -0.259630
  234. };
  235.  
  236.  
  237. /* The "craft" structure defines the current physical attributes of
  238.    the spacecraft. */
  239.  
  240. struct {
  241.     int fuel;        /* fuel remaining */
  242.     int index;       /* array index into lc_flame/lc_noflame which indicates
  243.          the current rotation of the spacecraft */
  244.     int collision;   /* did the craft collide with something */
  245.     double altitude; /* altitude above surface */
  246.     double range;    /* position along surface */
  247.     double vel_x;    /* velocity x component */
  248.     double vel_y;    /* velocity y component */
  249.     double vel;      /* velocity vector */
  250.     double prev_vel; /* previous velocity - need for landing speed */
  251. } craft;
  252.  
  253. /*
  254.  * calculate the new position of the spacecraft.  "burn" is 1 if we are
  255.  * currently burning fuel, 0 if not.  we maintain a coordinate system
  256.  * using altitude and range, and convert to screen x,y coordinates.
  257.  * return value indicates whether we actually burned any fuel.
  258.  * you could probably make this function faster...
  259.  */
  260.  
  261. int compute_pos(int burn)
  262. {
  263.     double v0;
  264.     double x0;
  265.     double accel_x;
  266.     double accel_y;
  267.     int did_burn;
  268.     
  269.     /* burn some fuel if there's any left */
  270.     if (burn && craft.fuel) {
  271.    accel_x = (THRUST - GRAVITY) * cosval[craft.index];
  272.    accel_y = -(THRUST - GRAVITY) * sinval[craft.index];
  273.    --craft.fuel;
  274.    did_burn = 1;
  275.     } else {
  276.    accel_x = 0;
  277.    accel_y = -GRAVITY;
  278.    did_burn = 0;
  279.     }
  280.     
  281.     v0 = craft.vel_x;
  282.     craft.vel_x = v0 + accel_x;
  283.     x0 = craft.range;
  284.     craft.range = x0 + v0 + (accel_x/2);
  285.     if (craft.range < 0) {
  286.    /* bounce off the edge of the moon (lose some velocity) */
  287.    craft.range = 0;
  288.    craft.vel_x = -craft.vel_x/3;
  289.    accel_x = -accel_x/3;
  290.     }
  291.     else if (craft.range >= MAX_RANGE) {
  292.    craft.range = MAX_RANGE;
  293.    craft.vel_x = -craft.vel_x/3;
  294.    accel_x = -accel_x/3;
  295.     }
  296.  
  297.     v0 = craft.vel_y;
  298.     craft.vel_y = v0 + accel_y;
  299.     x0 = craft.altitude;
  300.     craft.altitude = x0 + v0 + (accel_y/2);
  301.     if (craft.altitude < 0) {
  302.    craft.altitude = 0;
  303.    craft.vel_y = 0;
  304.    accel_y = 0;
  305.     }
  306.     else if (craft.altitude >= MAX_ALTITUDE) {
  307.    craft.altitude = MAX_ALTITUDE;
  308.    craft.vel_y = 0;
  309.     }
  310.  
  311.     /* calculate velocity vector */
  312.     craft.prev_vel = craft.vel;
  313.     craft.vel = sqrt(craft.vel_x * craft.vel_x + craft.vel_y * craft.vel_y);
  314.  
  315.     /* convert lunar position to bitmap coordinates */
  316.     lem->anim->x = craft.range * bmwidth / MAX_RANGE;
  317.     lem->anim->y = (bmheight-30) - (craft.altitude * (bmheight-30) / MAX_ALTITUDE);
  318.  
  319.     return did_burn;
  320. }
  321.  
  322. /*
  323.  * collision handler for craft-to-background checks.  the pallete has been
  324.  * created such that the background colors of interest are in the third
  325.  * bitplane (colors 4,5,6,7).  we want to ignore the mountains but collide
  326.  * with the rocks on the ground, so the collision handler is enabled only
  327.  * below a certain altitude.  see the main loop for where we enable and
  328.  * disable the collision handler.
  329.  */
  330. void grounded(struct anim_struct *anim, struct coll_bg_struct *point, int color)
  331. {
  332.     craft.collision = color;
  333. }
  334.  
  335. /*
  336.  * show current stats on the control panel
  337.  */
  338. void show_stats(void)
  339. {
  340.     char cpbuf[30];
  341.     
  342.     /* update current information on the control panel */
  343.     SetAPen(&rp, 3); /* green */
  344.  
  345.     /* divide altitude and velocity by 10 for a more reasonable output */
  346.     sprintf(cpbuf, "%05d", (int)craft.altitude / 10);
  347.     Move(&rp, 22, 12);
  348.     Text(&rp, cpbuf, 5);
  349.     sprintf(cpbuf, "%05d", (int)craft.vel / 10);
  350.     Move(&rp, 85, 12);
  351.     Text(&rp, cpbuf, 5);
  352.     if (craft.fuel <= LOW_FUEL) {
  353.    SetAPen(&rp, 2); /* red */
  354.     }
  355.     sprintf(cpbuf, "%05d", (int)craft.fuel);
  356.     Move(&rp, 153, 12);
  357.     Text(&rp, cpbuf, 5);
  358.  
  359.     SetAPen(&rp, 3); /* green */
  360.     sprintf(cpbuf, "%02d:%02d", elapsed_mins, elapsed_secs);
  361.     Move(&rp, 219, 12);
  362.     Text(&rp, cpbuf, 5);
  363. }
  364.  
  365. /*
  366.  * VB interrupt handler: scroll the display when the spacecraft
  367.  * gets near one of the edges.
  368.  */
  369.  
  370. unsigned long vbcounter;
  371.  
  372. void __interrupt __saveds scroll(void)
  373. {
  374.     int dx, dy;
  375.  
  376.     ++vbcounter;
  377.     
  378.     /* keep track of elapsed time */
  379.     if (++elapsed_ticks == TICKS_PER_SEC) {
  380.    elapsed_ticks = 0;
  381.    if (++elapsed_secs == 60) {
  382.        elapsed_secs = 0;
  383.        ++elapsed_mins;
  384.    }
  385.     }
  386.     
  387.     /* keep track of when it's ok for the rock star to dance */
  388.     if (--dance_time <= 0) {
  389.    time_to_dance = 1;
  390.    dance_time = DANCE_DELAY;
  391.     }
  392.  
  393.     /* don't scroll if showing the explosion */
  394.     if (lem->seq == BOOM) {
  395.    return;
  396.     }
  397.     
  398.     if (lem->anim->x < vp.xoff + X_SCROLLPOS) {
  399.    dx = vp.xoff + X_SCROLLPOS - lem->anim->x;
  400.     } else if (lem->anim->x > vp.xoff + DWIDTH - X_SCROLLPOS) {
  401.    dx = vp.xoff + DWIDTH - X_SCROLLPOS - lem->anim->x;
  402.     } else {
  403.    dx = 0;
  404.     }
  405.  
  406.     if (lem->anim->y < vp.yoff + Y_SCROLLTOP) {
  407.    dy = vp.yoff + Y_SCROLLTOP - lem->anim->y;
  408.     } else if (lem->anim->y > vp.yoff + DHEIGHT - Y_SCROLLBOT) {
  409.    dy = vp.yoff + DHEIGHT - Y_SCROLLBOT - lem->anim->y;
  410.     } else {
  411.    dy = 0;
  412.     }
  413.  
  414.     if (dx != 0 || dy != 0) {
  415.    gs_scroll_vp(display, 0, -dx, -dy, 1);
  416.     }
  417. }
  418.  
  419.  
  420. /*
  421.  * delay specified number of vb ticks, sync with display
  422.  */
  423. void mydelay(int vbticks)
  424. {
  425.     int n = vbcounter + vbticks;
  426.     while (vbcounter < n);
  427.     while (display->flags & GSV_FLIP);   /* while page not flipped yet */
  428. }
  429.  
  430. /*
  431.  * display an error message (we should never need this)
  432.  */
  433.  
  434. struct IntuiText hdrtext = { 1,0,JAM2,10,16,NULL,NULL,NULL };
  435. struct IntuiText fataltext = { 2,0,JAM2,10,32,NULL,NULL,&hdrtext };
  436. struct IntuiText canceltext = { 1,0,JAM2,7,3,NULL,"Cancel",NULL };
  437.  
  438. void myerror(char *text)
  439. {
  440.     hdrtext.IText = "Bad news from the moon...";
  441.     fataltext.IText = text;
  442.     AutoRequest(NULL, &fataltext, NULL, &canceltext, 0, 0, 600, 90);
  443. }
  444.  
  445. /*
  446.  *  cleanup all resources and exit
  447.  */
  448.  
  449. void cleanup(void)
  450. {
  451.     gs_close_sound();
  452.     gs_free_sound(&thrust);
  453.     gs_free_sound(&whoop);
  454.     gs_free_sound(&ping);
  455.     gs_free_sound(&fill);
  456.     gs_free_sound(&kaboom);
  457.     gs_free_sound(&landed);
  458.     
  459.     if (dlist > -1) _gs_free_display_list(dlist);
  460.     if (scroller) _gs_remove_vb_server(scroller);
  461.     if (lem) gs_free_cplx(lem, 1);
  462.     if (rockstar) gs_free_cplx(rockstar, 1);
  463.     if (display) gs_remove_display(display);
  464.     /* since we allocated our own bitmaps we must free them */
  465.     if (vp.bitmap1) gs_free_bitmap(vp.bitmap1);
  466.     if (vp.bitmap2) gs_free_bitmap(vp.bitmap2);
  467.     if (vp2.bitmap1) gs_free_bitmap(vp2.bitmap1);
  468.     if (vp2.bitmap2) gs_free_bitmap(vp2.bitmap2);
  469.  
  470.     /* free up MED stuff */
  471.     if (tune) {
  472.    StopPlayer();
  473.    UnLoadModule(tune);
  474.    FreePlayer();
  475.     }
  476.     if (MEDPlayerBase) CloseLibrary(MEDPlayerBase);
  477.     
  478.     gs_close_libs();
  479.     exit(0);
  480. }
  481.  
  482.  
  483. /*
  484.  * setup all game data
  485.  */
  486.  
  487. int setup(void)
  488. {
  489.     struct anim_load_struct load = {
  490.    "lc.cplx", 0, 0, 0, 0, 8, 0, 1, ANIMLOAD_NOCOLOR
  491.     };
  492.     struct anim_load_struct loadrs = {
  493.    "rs.cplx", 0, 0, 0, 0, 8, 0, 1, ANIMLOAD_NOCOLOR
  494.     };
  495.     struct loadILBM_struct loadimg = {
  496.    "landscape.iff", 0, 0, lunar_cmap, NUM_COLORS, 0, 0, 0, 0, 0, 0, 0,
  497.    ILBM_COLOR | ILBM_ALLOC2, 0xff, 0xff
  498.     };
  499.     struct loadILBM_struct loadimg2 = {
  500.    "panel.iff", 0, 0, vp2_cmap, VP2_NUM_COLORS, 0, 0, 0, 0, 0, 0, 0,
  501.    ILBM_COLOR | ILBM_ALLOC2, 0xff, 0xff
  502.     };
  503.  
  504.     int result;
  505.     int page;
  506.     
  507.     /* open amiga libraries */
  508.     if (gs_open_libs(DOS|GRAPHICS|INTUITION|MATHDBLB|MATHDBLT|MATHTRANS,0)) {
  509.    exit(1);
  510.     }
  511.  
  512.     /* Open the MEDplayer library */
  513.     MEDPlayerBase=(struct Library *)OpenLibrary("medplayer.library",0);
  514.     if (!MEDPlayerBase) {
  515.    myerror("Need medplayer.library");
  516.    return -1;
  517.     }
  518.     
  519.     /* Load the mod */
  520.     tune = LoadModule("mod.MoonRocks");
  521.     if (!tune) {
  522.    myerror("Couldn't load mod.MoonRocks");
  523.    return -1;
  524.     }
  525.  
  526.     /* Initialize the MED player */
  527.     if (GetPlayer(0)) {
  528.    myerror("Can't Initialize MED player!");
  529.     }
  530.    
  531.     /*
  532.      * load the lunar landscape. this creates two superbitmaps for the
  533.      * double-buffered scrolling viewport, and fills in the color table
  534.      * used by all game objects.
  535.      */
  536.     result = gs_loadILBM(&loadimg);
  537.     if (result) {
  538.    myerror(loadimg.file);
  539.    return result;
  540.     }
  541.  
  542.     /* viewport will use the bitmaps just allocated */
  543.     vp.bitmap1 = loadimg.bitmap1;
  544.     vp.bitmap2 = loadimg.bitmap2;
  545.     bmwidth=vp.bitmap1->BytesPerRow*8;
  546.     bmheight=vp.bitmap1->Rows;
  547.  
  548.     /* load the control panel image */
  549.     result = gs_loadILBM(&loadimg2);
  550.     if (result) {
  551.    myerror(loadimg.file);
  552.    return result;
  553.     }
  554.     vp2.bitmap1 = loadimg2.bitmap1;
  555.     vp2.bitmap2 = loadimg2.bitmap2;
  556.     cp_bitmaps[0] = vp2.bitmap1;
  557.     cp_bitmaps[1] = vp2.bitmap2;
  558.     
  559.     /* control panel needs a RastPort so we can draw text to it */
  560.     InitRastPort(&rp);
  561.     rp.BitMap = vp2.bitmap1;
  562.     SetDrMd(&rp, JAM2);
  563.     SetBPen(&rp, 0); /* black */
  564.     
  565.     /* force topaz.8 in the control panel */
  566.     myfont = OpenFont(&sysfont);
  567.     if (!myfont) {
  568.    myerror("Can't open topaz.8 font");
  569.    return -1;
  570.     }
  571.     SetFont(&rp, myfont);
  572.  
  573.     /* load the spacecraft anim */
  574.     if (result = gs_load_anim(&load)) {
  575.    myerror(load.filename);
  576.    return result;
  577.     }
  578.     
  579.     /* get pointer to the loaded anim */
  580.     lem = load.anim_ptr.cplx;
  581.  
  582.     /* load the rock star anim */
  583.     if (result = gs_load_anim(&loadrs)) {
  584.    myerror(loadrs.filename);
  585.    return result;
  586.     }
  587.     
  588.     /* get pointer to the loaded anim */
  589.     rockstar = loadrs.anim_ptr.cplx;
  590.  
  591.     /* create the display */
  592.    #ifdef NTSC_MONITOR_ID
  593.       if (GfxBase->LibNode.lib_Version >= 36)   /* if WB 2.0 or higher */
  594.          {               /* this defeats mode promotion on AGA machines */
  595.          if (ModeNotAvailable(NTSC_MONITOR_ID))
  596.             {
  597.             lunar_display.modes = PAL_MONITOR_ID;
  598.             }
  599.          else
  600.             {
  601.             lunar_display.modes = NTSC_MONITOR_ID;
  602.             }
  603.          }
  604.    #endif
  605.     result = gs_create_display(&lunar_display);
  606.     if (result) {
  607.    myerror("gs_create_display failed");
  608.    return result;
  609.     }
  610.     display = &lunar_display;
  611.     
  612.     if ((dlist=_gs_get_display_list()) < 0) {
  613.    myerror("gs_get_display_list failed");
  614.    return result;
  615.     }
  616.  
  617.     /* perform other anim initialization */
  618.     gs_init_anim(dlist,display->vp->bitmap1, display->vp->bitmap2, NULL);
  619.     gs_set_anim_bounds(dlist,0, 0, bmwidth-1, bmheight-1);
  620.     gs_random(0);
  621.  
  622.     /* setup the sound system and load the sounds */
  623.     if (gs_open_sound(0,1,-10,2560)) {
  624.    myerror("gs_open_sound failed");
  625.    return -1;
  626.     }
  627.  
  628.     /* sound of the thrusters */
  629.     thrust.flags = SND_FAST;
  630.     if (result=gs_load_iff_sound(&thrust,0,"thrust.snd")) {
  631.    myerror("cannot load thrust.snd");
  632.    return result;
  633.     }
  634.     thrust.repeat = 0; /* loop forever */
  635.     
  636.     /* low fuel alert */
  637.     whoop.flags = SND_FAST;
  638.     if (result=gs_load_iff_sound(&whoop,0,"whoop.snd")) {
  639.    myerror("cannot load whoop.snd");
  640.    return result;
  641.     }
  642.     whoop.repeat = 0; /* loop forever */
  643.     
  644.     /* a nice explosion */
  645.     kaboom.flags = SND_FAST;
  646.     if (result=gs_load_raw_sound(&kaboom,"kaboom.snd")) {
  647.    myerror("cannot load kaboom.snd");
  648.    return result;
  649.     }
  650.  
  651.     /* startrek bridge sound */
  652.     ping.flags = SND_FAST;
  653.     if (result=gs_load_raw_sound(&ping,"ping.snd")) {
  654.    myerror("cannot load ping.snd");
  655.    return result;
  656.     }
  657.     ping.repeat = 0; /* loop forever */
  658.     
  659.     /* sound played when filling the gas tank */
  660.     fill.flags = SND_FAST;
  661.     if (result=gs_load_iff_sound(&fill,0,"fill.snd")) {
  662.    myerror("cannot load fill.snd");
  663.    return result;
  664.     }
  665.     fill.repeat = 0; /* loop forever */
  666.  
  667.     /* sound played when landing is successful */
  668.     landed.flags = SND_FAST;
  669.     if (result=gs_load_iff_sound(&landed,0,"landed.snd")) {
  670.    myerror("cannot load landed.snd");
  671.    return result;
  672.     }
  673.  
  674.     /* add the anims to the display */
  675.     if (result = gs_add_anim_cplx(dlist,lem, 0, 0, lc_noflame[craft.index], 0)) {
  676.    myerror("gs_add_anim_cplx failed");
  677.    return result;
  678.     }
  679.     if (result = gs_add_anim_cplx(dlist,rockstar, 0, 0, DANCE1, 0)) {
  680.    myerror("gs_add_anim_cplx failed");
  681.    return result;
  682.     }
  683.  
  684.     gs_draw_anims(dlist);
  685.     page = gs_next_anim_page(dlist);
  686.     rp.BitMap = cp_bitmaps[page];
  687.  
  688.     /* even more anim initialization */
  689.     gs_show_display(display,1);
  690.     gs_flip_display(display,1);
  691.     
  692.     /* setup the scrolling routine */
  693.     scroller = gs_add_vb_server(&scroll, 0);
  694.     if (!scroller) {
  695.    myerror("gs_add_vb_server failed");
  696.    return -5;
  697.     }
  698.     
  699.     /* setup collision handler for things on the ground */
  700.     gs_set_collision_bg(dlist, grounded);
  701.  
  702.     return 0;
  703. }
  704.  
  705. /*
  706.  * flip to the next display page, making sure that the
  707.  * rastport bitmap for the control panel is in sync.
  708.  */
  709. void flipper(void)
  710. {
  711.     int page;
  712.  
  713.     gs_draw_anims(dlist);
  714.     page = gs_next_anim_page(dlist);
  715.     rp.BitMap = cp_bitmaps[page];
  716.     gs_flip_display(display,1);
  717. }
  718.  
  719. /*
  720.  * Start background noise - depending on whether the rock star is
  721.  * visible, it's either the startrek bridge sound, or some music.
  722.  */
  723. void start_background_noise(void)
  724. {
  725.     if (rockstar_visible) {
  726.    /* Continue playing the mod */
  727.    ContModule(tune);
  728.     } else {
  729.    gs_start_sound(&ping, PING_CHANNEL);
  730.     }
  731. }
  732.  
  733. /*
  734.  * Stop whichever background noise is playing.
  735.  */
  736. void stop_background_noise(void)
  737. {
  738.     if (rockstar_visible) {
  739.    /* Stop playing the mod */
  740.    StopPlayer();
  741.     } else {
  742.    gs_stop_sound(PING_CHANNEL);
  743.     }
  744. }
  745.  
  746. /*
  747.  * animate the dancing rock star.  time_to_dance is set in the vb interrupt
  748.  * when enough time has elapsed to do the next dance frame.  rockstar_time is
  749.  * when it's time to switch to a different dance, or when to make him
  750.  * materialize if he's currently invisible.
  751.  */
  752. void dance(void)
  753. {
  754.     if (rockstar_visible) {
  755.    /* switch to a different dance animation every once in awhile */
  756.    if (vbcounter >= rockstar_time) {
  757.        if (rockstar->seq == DANCE1) {
  758.       gs_set_cplx_seq(rockstar, DANCE2, rockstar->anim->x, rockstar->anim->y);
  759.        } else {
  760.       gs_set_cplx_seq(rockstar, DANCE1, rockstar->anim->x, rockstar->anim->y);
  761.        }
  762.        
  763.        /* switch again at a random time */
  764.        rockstar_time = vbcounter + (gs_random(5) + 5) * TICKS_PER_SEC;
  765.    }
  766.    if (time_to_dance) {
  767.        time_to_dance = 0;
  768.        gs_anim_cplx(rockstar, rockstar->anim->x, rockstar->anim->y);
  769.    }
  770.     }
  771.     else if (vbcounter >= rockstar_time && allow_rockstar) {
  772.  
  773.    /* time for him to materialize */
  774.    gs_enable_cplx(rockstar);
  775.    rockstar_visible = 1;
  776.  
  777.    /* he materializes in the reclining position and must stand up */
  778.    gs_set_cplx_seq(rockstar, STANDUP, rockstar->anim->x, rockstar->anim->y);
  779.    gs_set_cplx_cell(rockstar, 0);
  780.  
  781.    /* he'll start dancing in three seconds */
  782.    rockstar_time = vbcounter + 3 * TICKS_PER_SEC;
  783.  
  784.    /* stop the ping and start the music he'll be dancing to */
  785.    gs_stop_sound(PING_CHANNEL);
  786.    PlayModule(tune);
  787.     }
  788. }
  789.  
  790. void show_panel(int offset)
  791. {
  792.     gs_scroll_vp(display, 1, 0, offset, 1);
  793. }
  794.  
  795. /*
  796.  * user paused the game
  797.  */
  798. void pause_game(int current_panel)
  799. {
  800.     /* user pressed LMB to get here, wait for it to be released */
  801.     while (gs_joystick(0)&JOY_BUTTON1) {}
  802.  
  803.     /* scroll the control panel to show the pause display */
  804.     show_panel(VP_PAUSED - current_panel);
  805.     
  806.     /* wait for response */
  807.     while (1) {
  808.    if (gs_joystick(0) & JOY_BUTTON1) {
  809.        /* mouse button - resume game */
  810.        /* but wait for LMB to be released first */
  811.        while (gs_joystick(0)&JOY_BUTTON1) {}
  812.  
  813.        /* scroll the control panel to return to the game display */
  814.        show_panel(-VP_PAUSED + current_panel);
  815.        return;
  816.    }
  817.    if (gs_joystick(1) & JOY_BUTTON1) {
  818.        /* joystick button - quit game */
  819.        Permit();
  820.        cleanup();
  821.    }
  822.  
  823.    /* dance continues even while paused */
  824.    dance();
  825.    mydelay(1);
  826.    flipper();
  827.     }
  828. }
  829.  
  830. /*
  831.  * landed at fuel station
  832.  */
  833. void refuel(void)
  834. {
  835.     stop_background_noise();
  836.     mydelay(25);
  837.     gs_start_sound(&fill, FILL_CHANNEL);
  838.  
  839.     craft.vel_x = 0;
  840.     craft.vel_y = 0;
  841.     craft.index = 0;
  842.     gs_set_cplx_seq(lem, LEM00, lem->anim->x, lem->anim->y);
  843.  
  844.     /* fill the tank */
  845.     while (craft.fuel < MAX_FUEL) {
  846.       
  847.    craft.fuel += 3;
  848.    if (craft.fuel > MAX_FUEL) {
  849.        craft.fuel = MAX_FUEL;
  850.    }
  851.  
  852.    if (gs_joystick(0)&JOY_BUTTON1) {
  853.  
  854.        pause_game(0);
  855.    }
  856.  
  857.    show_stats();
  858.    gs_anim_cplx(lem, lem->anim->x, lem->anim->y);
  859.    dance();
  860.  
  861.    mydelay(1);
  862.    flipper();
  863.     }
  864.     gs_stop_sound(FILL_CHANNEL);
  865.     mydelay(25);
  866.     start_background_noise();
  867.  
  868.     /* wait for liftoff */
  869.     while (1) {
  870.  
  871.    if (gs_joystick(0)&JOY_BUTTON1) {
  872.  
  873.        pause_game(0);
  874.    }
  875.  
  876.    if (gs_joystick(1) & JOY_BUTTON1) {
  877.  
  878.        /* need to give the craft a good kick to get it away from the
  879.         * fuel platform.  otherwise the collision detection in the
  880.         * main loop will bring us right back here.
  881.         */
  882.        craft.altitude += 500;
  883.        craft.collision = 0;
  884.        return;
  885.    }
  886.  
  887.    /* continue page-flipping to show the clock ticking */
  888.    show_stats();
  889.    gs_anim_cplx(lem, lem->anim->x, lem->anim->y);
  890.    dance();
  891.    mydelay(1);
  892.    flipper();
  893.     }
  894.        
  895. }
  896.  
  897. /*
  898.  * spacecraft crashed into something
  899.  */
  900. void crash(void)
  901. {
  902.     int i;
  903.     
  904.     stop_background_noise();
  905.     gs_stop_sound(THRUST_CHANNEL);
  906.     gs_stop_sound(WHOOP_CHANNEL);
  907.     gs_start_sound(&kaboom, KABOOM_CHANNEL);
  908.  
  909.     /* show the crashed control panel */
  910.     show_panel(VP_CRASHED);
  911.     
  912.     /* adjust anim position because explosion is bigger than craft */
  913.     lem->anim->x -= 40;
  914.     lem->anim->y -= 20;
  915.     gs_set_cplx_seq(lem, BOOM, lem->anim->x, lem->anim->y);
  916.     gs_set_cplx_cell(lem, 0);
  917.  
  918.     /* animate the explosion for a few seconds */
  919.     for (i = 0; i < 90; i++) {
  920.       
  921.    if (gs_joystick(0)&JOY_BUTTON1) {
  922.  
  923.        pause_game(VP_CRASHED);
  924.    }
  925.    show_stats();
  926.    gs_anim_cplx(lem, lem->anim->x, lem->anim->y);
  927.    dance();
  928.        
  929.    /* explosion sequence is slower than main animation */
  930.    mydelay(5);
  931.    flipper();
  932.     }
  933.  
  934.     /* restore the main control panel */
  935.     show_panel(-VP_CRASHED);
  936.  
  937.     /* in case he appeared while we crashed... */
  938.     stop_background_noise();
  939. }
  940.  
  941. /*
  942.  * successful landing.  returns non-zero if won the game, else 0.
  943.  */
  944. int safe_landing(void)
  945. {
  946.     int panel;
  947.     int dist;
  948.     
  949.     /* wait for joystick button to be released */
  950.     while (gs_joystick(1)&JOY_BUTTON1) {}
  951.  
  952.     gs_stop_sound(THRUST_CHANNEL);
  953.     craft.vel_x = 0;
  954.     craft.vel_y = 0;
  955.     craft.index = 0;
  956.     gs_set_cplx_seq(lem, LEM00, lem->anim->x, lem->anim->y);
  957.  
  958.     /* did we land near the rock star? */
  959.     if (rockstar_visible) {
  960.  
  961.    dist = abs(rockstar->anim->x - lem->anim->x);
  962.    if (dist <= CLOSE_ENOUGH) {
  963.  
  964.        /* we have a winner! */
  965.        panel = VP_SUCCESS;
  966.        show_panel(panel);
  967.  
  968.        gs_stop_sound(WHOOP_CHANNEL);
  969.  
  970.        /* Stop playing the mod */
  971.        StopPlayer();
  972.        mydelay(5);
  973.        gs_start_sound(&landed, LANDED_CHANNEL);
  974.        mydelay(5);
  975.  
  976.        /* what for congrats to finish, then restart the mod */
  977.        while (gs_sound_check() & LANDED_CHANNEL) {}
  978.        PlayModule(tune);
  979.        
  980.    } else {
  981.  
  982.        /* didn't land close enough */
  983.        panel = VP_VISIBLE;
  984.        show_panel(panel);
  985.    }
  986.    
  987.     } else {
  988.    /* he's not even visible yet! */
  989.    panel = VP_NOWHERE;
  990.    show_panel(panel);
  991.     }
  992.  
  993.  
  994.     /* wait for liftoff */
  995.     while (1) {
  996.  
  997.    if (gs_joystick(0)&JOY_BUTTON1) {
  998.  
  999.        pause_game(panel);
  1000.    }
  1001.  
  1002.    if (gs_joystick(1) & JOY_BUTTON1) {
  1003.  
  1004.        craft.altitude += 300;
  1005.        craft.collision = 0;
  1006.  
  1007.        /* flip back to the main control panel */
  1008.        show_panel(-panel);
  1009.  
  1010.        /* return result of landing close */
  1011.        if (panel == VP_SUCCESS) {
  1012.       stop_background_noise();
  1013.       return 1;
  1014.        } else {
  1015.       start_background_noise();
  1016.       return 0;
  1017.        }
  1018.    }
  1019.  
  1020.    show_stats();
  1021.    gs_anim_cplx(lem, lem->anim->x, lem->anim->y);
  1022.    dance();
  1023.    mydelay(5);
  1024.    flipper();
  1025.     }
  1026. }
  1027.  
  1028. /*
  1029.  * main program:  set everything up and then play the game (duh...)
  1030.  */
  1031.  
  1032. void main(void)
  1033. {
  1034.     int result;
  1035.     unsigned char joy;
  1036.     int burn;
  1037.     int thrusting = 0;
  1038.     int joycount;
  1039.     
  1040.     /* setup the animation system */
  1041.     if ((result = setup()) != 0) {
  1042.    char err[60];
  1043.    sprintf(err, "setup failed (%d)", result);
  1044.    myerror(err);
  1045.    cleanup();
  1046.     }
  1047.  
  1048.     /* play multiple times until mouse button is pressed */
  1049.     Forbid();
  1050.     while (1) {
  1051.    
  1052.    /*
  1053.     * spacecraft begins with a full tank, at a random position and
  1054.     * velocity.  what's really cool about this is that the scroll
  1055.     * interrupt will automatically reposition the superbitmap so
  1056.     * that the spacecraft is visible.  the main loop never has
  1057.     * to care what the physical display looks like!
  1058.     */
  1059.    craft.fuel = MAX_FUEL;
  1060.    craft.altitude = MAX_ALTITUDE;
  1061.    craft.range = (gs_random(bmwidth - 200) + 100) * MAX_RANGE / bmwidth;
  1062.    craft.vel_x = gs_random(200) - 100;
  1063.    if (craft.vel_x > 0) {
  1064.        craft.index = LC_ANIM_COUNT-1;
  1065.    } else {
  1066.        craft.index = 1;
  1067.    }
  1068.    craft.vel_y = 0;
  1069.    craft.collision = 0;
  1070.    compute_pos(0);
  1071.  
  1072.    /* reset the elapsed time counter */
  1073.    elapsed_mins = 0;
  1074.    elapsed_secs = 0;
  1075.    elapsed_ticks = 0;
  1076.    
  1077.    /* place rock star at a random ground position */
  1078.    rockstar->anim->x = gs_random(bmwidth - 100) + 50;
  1079.    rockstar->anim->y = bmheight-30;
  1080.     
  1081.    /* but he's invisible for awhile */
  1082.    gs_clear_cplx(rockstar);
  1083.    rockstar_visible = 0;
  1084.    allow_rockstar = 1;
  1085.    
  1086.    /* he will materialize at a random time at least 40 seconds after
  1087.       the start of the game. */
  1088.    rockstar_time = vbcounter + (40 + gs_random(90)) * TICKS_PER_SEC;
  1089.    
  1090.    joycount = JOY_INTERVAL;
  1091.  
  1092.    show_stats();
  1093.    
  1094.    start_background_noise();
  1095.    
  1096.    /*
  1097.     * Here is the main game loop.  Simply watch the joystick and move
  1098.     * the anim around appropriately.  We continue in this inner loop
  1099.     * until we land near the target or we crash.
  1100.     */
  1101.    while (1) {
  1102.  
  1103.        if (gs_joystick(0)&JOY_BUTTON1) {
  1104.  
  1105.       pause_game(0);
  1106.        }
  1107.  
  1108.        /*
  1109.         * Check the joystick.  Left and right will rotate the spacecraft
  1110.         * 15 degrees in either direction.  Button will burn some fuel.
  1111.         */
  1112.        joy = gs_joystick(1);
  1113.        
  1114.        /*
  1115.         * Check rotational motion every JOY_INTERVAL times through this
  1116.         * loop.  If we check it too often, the spacecraft rotates too
  1117.         * fast to be playable.  Thrust button is checked every time.
  1118.         */
  1119.        if (--joycount <= 0) {
  1120.       joycount = JOY_INTERVAL;
  1121.       
  1122.       if (joy & JOY_RIGHT) {
  1123.           /* rotate clockwise */
  1124.           if (++craft.index == LC_ANIM_COUNT) craft.index = 0;
  1125.       } else if (joy & JOY_LEFT) {
  1126.           /* rotate counter-clockwise */
  1127.           if (--craft.index < 0) craft.index = LC_ANIM_COUNT-1;
  1128.       }       
  1129.        }
  1130.        
  1131.        if (joy & JOY_BUTTON1) {
  1132.       /* calculate the next spacecraft position with full throttle */
  1133.       burn = compute_pos(1);
  1134.        } else {
  1135.       /* calculate the next spacecraft position with no throttle */
  1136.       burn = compute_pos(0);
  1137.        }
  1138.        
  1139.        /* show the spacecraft with or without flame depending on whether
  1140.           we burned any fuel */
  1141.        if (burn) {
  1142.  
  1143.       /* we burned fuel this time.  show the spacecraft with flame */
  1144.       gs_set_cplx_seq(lem, lc_flame[craft.index], lem->anim->x, lem->anim->y);
  1145.       /* turn on the thrust sound if it's not already on */
  1146.       if (!thrusting) {
  1147.           thrusting = 1;
  1148.           gs_start_sound(&thrust, THRUST_CHANNEL);
  1149.       }
  1150.  
  1151.       if (craft.fuel == LOW_FUEL) {
  1152.           /* we're running on fumes! */
  1153.           gs_start_sound(&whoop, WHOOP_CHANNEL);
  1154.       } else if (craft.fuel == 0) {
  1155.           /* not even any fumes left! */
  1156.           gs_stop_sound(WHOOP_CHANNEL);
  1157.           gs_stop_sound(THRUST_CHANNEL);
  1158.           stop_background_noise();
  1159.           thrusting = 0;
  1160.       }
  1161.        
  1162.        } else {
  1163.       /* no fuel burned this time, show spacecraft without flame */
  1164.       gs_set_cplx_seq(lem, lc_noflame[craft.index], lem->anim->x, lem->anim->y);
  1165.       /* turn off thrust sound if necessary */
  1166.       if (thrusting) {
  1167.           gs_stop_sound(THRUST_CHANNEL);
  1168.           thrusting = 0;
  1169.       }
  1170.        }
  1171.    
  1172.        /* we want background collision checking to occur only when the
  1173.         * spacecraft is near the bottom of the bitmap (i.e. it can crash
  1174.         * into the rocks on the ground but not the mountains in the
  1175.         * distance).  we check the ANIM_COLLISION_BG bit in the flags
  1176.         * so that we enable or disable collision checking only once
  1177.         * each time we cross the threshold.
  1178.         */
  1179.        if (lem->anim->y > GROUND_THRESHOLD && !(lem->anim->flags & ANIM_COLLISION_BG)) {
  1180.       gs_enable_cplx_collision_bg(lem);
  1181.        } else if (lem->anim->y <= GROUND_THRESHOLD && (lem->anim->flags & ANIM_COLLISION_BG)) {
  1182.       gs_disable_cplx_collision_bg(lem);
  1183.        }
  1184.  
  1185.        /* show current stats */
  1186.        show_stats();
  1187.  
  1188.        /* show the next spacecraft animation frame as determined above */
  1189.        gs_anim_cplx(lem, lem->anim->x, lem->anim->y);
  1190.        
  1191.        /* rock star is dancing */
  1192.        dance();
  1193.        
  1194.        /* update the off-screen bitmap, then display it */
  1195.        mydelay(1);
  1196.        flipper();
  1197.  
  1198.        /* if we landed on the fuel platform, fill 'er up */
  1199.        /* this happens if collide with background color white or yellow */
  1200.        /* make sure landed slowly and more-or-less upright */
  1201.        if (craft.collision == 5 || craft.collision == 6) {
  1202.  
  1203.       if (craft.prev_vel <= SAFE_SPEED &&
  1204.           (craft.index == 0 || craft.index == 1 || craft.index == LC_ANIM_COUNT-1)) {
  1205.           /* landed on platform ok */
  1206.           if (craft.fuel < MAX_FUEL) {
  1207.          gs_stop_sound(THRUST_CHANNEL);
  1208.          thrusting = 0;
  1209.          refuel();
  1210.           }
  1211.       } else {
  1212.           /* crashed on platform */
  1213.           crash();
  1214.           break;
  1215.       }
  1216.        } else if (craft.collision) {
  1217.       /* collided with a rock */
  1218.       crash();
  1219.       break;
  1220.        } else if (craft.altitude == 0) {
  1221.       /* on the ground, let's see how we landed */
  1222.       gs_stop_sound(THRUST_CHANNEL);
  1223.       gs_stop_sound(WHOOP_CHANNEL);
  1224.  
  1225.       /* don't let rock star appear nearby if he's not visible yet */
  1226.       if (!rockstar_visible) {
  1227.           gs_stop_sound(PING_CHANNEL);
  1228.           allow_rockstar = 0;
  1229.       }
  1230.       
  1231.       craft.vel = 0;
  1232.       mydelay(2);
  1233.  
  1234.       if (craft.prev_vel <= SAFE_SPEED &&
  1235.           (craft.index == 0 || craft.index == 1 || craft.index == LC_ANIM_COUNT-1)) {
  1236.           /* a gentle upright landing! */
  1237.           thrusting = 0;
  1238.           if (safe_landing()) {
  1239.          /* won the game, start over */
  1240.          break;
  1241.           }
  1242.           /* otherwise continue the search */
  1243.           allow_rockstar = 1;
  1244.  
  1245.           /* if we sat on the ground waiting for him to appear,
  1246.              don't let him appear right away */
  1247.           if (!rockstar_visible) {
  1248.          rockstar_time = vbcounter + (gs_random(5) + 20) * TICKS_PER_SEC;
  1249.           }
  1250.       } else {
  1251.           /* too fast or tilted or hit a rock */
  1252.           crash();
  1253.           break;
  1254.       }
  1255.        }
  1256.    }
  1257.     }
  1258. }
  1259.  
  1260.